/* eslint-disable no-param-reassign */
/* eslint-disable vue/no-mutating-props */
import { getViewProvider, IViewProvider } from '@ibiz-template/runtime';
import { useNamespace } from '@ibiz-template/vue3-util';
import { defineComponent, h, PropType, ref, resolveComponent } from 'vue';
import './view-shell.scss';
import { IAppView } from '@ibiz/model-core';
import { RuntimeError } from '@ibiz-template/core';

export const IBizViewShell = defineComponent({
  name: 'IBizViewShell',
  props: {
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams> },
    modelData: { type: Object as PropType<IAppView> },
    viewId: { type: String },
  },
  setup(props) {
    const ns = useNamespace('view-shell');
    const isComplete = ref(false);
    const errMsg = ref('');
    const provider = ref<IViewProvider>();
    const viewModelData = ref<IAppView | undefined>();
    // 初始化方法
    const init = async (): Promise<void> => {
      let viewModel: IAppView | undefined;
      if (props.modelData) {
        viewModel = props.modelData;
      } else {
        viewModel = await ibiz.hub.getAppView(props.viewId!);
      }
      if (!viewModel) {
        throw new RuntimeError('未找到视图模型');
      }
      viewModelData.value = viewModel;
      try {
        provider.value = await getViewProvider(viewModel);
      } catch (error) {
        ibiz.log.error(error);
        errMsg.value = (error as IData).message;
      } finally {
        isComplete.value = true;
      }
    };

    init();

    return { ns, isComplete, errMsg, viewModelData, provider };
  },
  render() {
    if (this.isComplete && this.provider) {
      return h(
        resolveComponent(this.provider.component) as string,
        {
          context: this.$props.context,
          params: this.$props.params,
          modelData: this.viewModelData,
          ...this.$attrs,
        },
        this.$slots,
      );
    }
    return (
      <div class={this.ns.b()} v-loading={!this.isComplete}>
        {this.isComplete ? this.errMsg : null}
      </div>
    );
  },
});
